﻿using IBLL.SH_ADF0979IBLL;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using MysqlforDataWatch;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Tools;
using Tools.DateTimeOperation;
using Tools.FileOperation;
using Tools.MyConfig;

namespace RLDA_VehicleData_Watch.Controllers.DataProcess
{
    public class DataImportController : Controller
    {
        private readonly ILogger<DataImportController> _logger;
        private readonly IAnalysisData_All_IBLL _IAnalysisData_All_Service;
        private readonly IAnalysisData_PUMA_IBLL _IAnalysisData_PUMA_Service;
        private readonly IBrakeDistribution_IBLL _IBrakeDistribution_IBLL;
        private readonly ISpeedDistribution_ACC_IBLL _ISpeedDistribution_ACC_IBLL;
        private readonly ISteeringDistribution_IBLL _ISteeringDistribution_IBLL;
        private readonly IThrottleDistribution_IBLL _IThrottleDistribution_IBLL;
        private readonly IEngineSpeedDisDistribution_IBLL _IEngineSpeedDisDistribution_IBLL;
        private readonly IEngineSpeedTimeDistribution_IBLL _IEngineSpeedTimeDistribution_IBLL;
        private readonly IGPSRecord_IBLL _IGPSRecord_IBLL;
        private readonly IBumpDistribution_IBLL _IBumpDistribution_IBLL;
        private readonly IMemoryCache _memoryCache;//内存缓存
        private readonly DbContext _db;
        private static GetVehicleParafromSql _getVehicleParafromSql;
        private static Dictionary<string, VehicleIDPara> paradict = new Dictionary<string, VehicleIDPara>();//存储每个车的里程
        private static string inputpath;
        private static string resultpath;



        public DataImportController(IAnalysisData_All_IBLL IAnalysisData_All_Service, IAnalysisData_PUMA_IBLL IAnalysisData_PUMA_Service, 
            IBrakeDistribution_IBLL brakeDistribution_IBLL , ISpeedDistribution_ACC_IBLL speedDistribution_ACC_IBLL , ISteeringDistribution_IBLL steeringDistribution_IBLL,
           IThrottleDistribution_IBLL throttleDistribution_IBLL , IGPSRecord_IBLL gPSRecord_IBLL, IBumpDistribution_IBLL bumpDistribution_IBLL, 
           IEngineSpeedDisDistribution_IBLL IEngineSpeedDisDistribution_IBLL, IEngineSpeedTimeDistribution_IBLL IEngineSpeedTimeDistribution_IBLL, ILogger<DataImportController> logger, IMemoryCache memoryCache, DbContext db, GetVehicleParafromSql getVehicleParafromSql)
        {
            _IAnalysisData_All_Service = IAnalysisData_All_Service;
            _IAnalysisData_PUMA_Service= IAnalysisData_PUMA_Service;
            _IBrakeDistribution_IBLL = brakeDistribution_IBLL;
            _ISpeedDistribution_ACC_IBLL=speedDistribution_ACC_IBLL;
            _ISteeringDistribution_IBLL=steeringDistribution_IBLL;
            _IThrottleDistribution_IBLL=throttleDistribution_IBLL;
            _IEngineSpeedDisDistribution_IBLL=IEngineSpeedDisDistribution_IBLL ;
            _IEngineSpeedTimeDistribution_IBLL = IEngineSpeedTimeDistribution_IBLL;
            _IGPSRecord_IBLL =gPSRecord_IBLL;
            _IBumpDistribution_IBLL=bumpDistribution_IBLL;
            _logger = logger;
            _memoryCache= memoryCache;
            _db = db;
            _getVehicleParafromSql = getVehicleParafromSql;

        }
        public string GetVehicleParafromSql(string vehicleid)
        {
            //先用内存缓存来存储车辆参数
            var re = _memoryCache.GetOrCreate<VehicleIDPara>(vehicleid + "para", value =>
            {
                return _getVehicleParafromSql.GetDatafromSql(vehicleid); ;
            });

            if (re != null)
            {
                //初始化车辆参数字典，由于字典是静态字段，不同实例可以共享
                if (paradict.Count != 0)
                {
                    if (!paradict.ContainsKey(vehicleid))
                    {
                        paradict.Add(vehicleid, re);
                    }
                    else
                    {
                        paradict[vehicleid]=re;
                    }
                }
                else
                {
                    paradict.Add(vehicleid, re);
                }
                //_vehicleIDPara = re;
                if (re.importaccess == 1)
                {
                    return "yes";
                }
                else
                {
                    return "此车辆没有导入权限！请先添加！";
                }
            }
            else
            {
                //如果是null也要删除缓存数据，否则新添加的车辆就没法用了，会一直显示数据库未添加此车辆！
                _memoryCache.Remove(vehicleid + "para");
                return "数据库未添加此车辆！";
            }
        }

        /// <summary>
        /// 把input和result的统计值改为一张表，不单独分开来导入，当天如果有文件出错，当天的数据不会导入
        /// </summary>
        /// <param name="startdate"></param>
        /// <param name="enddate"></param>
        /// <param name="vehicleid"></param>
        /// <returns></returns>
        public async Task<List<string>> DataImportV2(string startdate, string enddate, string vehicleid)
        {
            if (paradict[vehicleid].importaccess == 1)//判断是否允许导入数据
            {

                if (startdate != null && enddate != null)
                {
                    int span = DateTimeOperation.DateDiff(startdate, enddate);
                    inputpath = paradict[vehicleid].importhalfhourpath;
                    List<string> listresult = new List<string>();
                    string filename = "";
                    try
                    {
                        var para = paradict[vehicleid];
                        for (int i = 0; i < span + 1; i++)
                        {
                            string date = FileOperator.DatetoName(Convert.ToDateTime(startdate).AddDays(i).ToString("yyyy-MM-dd")).Substring(5);//当前计算的日期文件夹名称
                            string inputfiletimeinfo = Path.Combine(inputpath, date);
                            //string outputfiletimeinfo = Path.Combine(resultpath, date);
                            //判断input子文件夹里是否有导入的flag
                            if (!FileOperator.DataImportCompleteFlag(inputfiletimeinfo))
                            {
                                //判断是否有数据上传完整
                                if (FileOperator.DataTransferCompleteFlag(inputfiletimeinfo, date))
                                {
                                    FileInfo[] filelist = FileOperator.Isfileexist(inputfiletimeinfo);
                                    if (filelist != null && filelist.Length > 0)
                                    {
                                        List<StatisticAllHalfHour> stalist = new List<StatisticAllHalfHour>();
                                        List<Brakerecognition> brklist = new List<Brakerecognition>();
                                        List<Bumprecognition> bmplist = new List<Bumprecognition>();
                                        List<Gpsrecord> gpslist = new List<Gpsrecord>();
                                        List<Speeddistribution> spdlist = new List<Speeddistribution>();
                                        List<Streeringrecognition> strlist = new List<Streeringrecognition>();
                                        List<Throttlerecognition> thrlist = new List<Throttlerecognition>();
                                        List<EngineRpmDistribution_Distance> engspddislist = new List<EngineRpmDistribution_Distance>();
                                        List<EngineRpmDistribution_Time> engspdtimelist = new List<EngineRpmDistribution_Time>();
                                        bool canbeimported = true;
                                        //先判断是否要导入gps，如果要导入，先去数据库创建此车辆的gps表，如数据库有此车的gps表，则不创建（可以自动创建了，不需要再去数据库创建）
                                        if (paradict[vehicleid].GPSImport == 1)
                                        {
                                            await _IGPSRecord_IBLL.CreateTable(vehicleid);
                                        }
                                        Console.WriteLine("开始读取数据" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        foreach (var file in filelist)
                                        {
                                            filename=file.Name;
                                            //读取单个csv文件的数据并存储到t
                                            var t = await CSVFileImport.getAllDatafromCSVforImport(file,true);
                                            var infostatisticresult = _IAnalysisData_All_Service.JudgeandMergeStatisticAllHalfHourData(file, t, ref stalist, vehicleid, in para);
                                            var infogpsresult = _IGPSRecord_IBLL.JudgeandMergeGPSDataperHalfHourV2(file, t, ref gpslist, vehicleid, in para);
                                            var infobrkresult = _IBrakeDistribution_IBLL.JudgeandMergeBrkDataperHalfHourV2(file, t, ref brklist, vehicleid, in para);
                                            var infospdresult = _ISpeedDistribution_ACC_IBLL.JudgeandMergeSpdDataperHalfHourV2(file, t, ref spdlist, vehicleid, in para);
                                            var infostrresult = _ISteeringDistribution_IBLL.JudgeandMergeSteeringDataperHalfHourV2(file, t, ref strlist, vehicleid, in para);
                                            var infothrresult = _IThrottleDistribution_IBLL.JudgeandMergeThrottleDataperHalfHourV2(file, t, ref thrlist, vehicleid, in para);
                                            var infoengspddisresult = _IEngineSpeedDisDistribution_IBLL.JudgeandMergeEngSpdDisDataperHalfHourV2(file, t, ref engspddislist, vehicleid, in para);
                                            var infoengspdtimeresult = _IEngineSpeedTimeDistribution_IBLL.JudgeandMergeEngSpdTimeDataperHalfHourV2(file, t, ref engspdtimelist, vehicleid, in para);
                                            var infobmpresult = _IBumpDistribution_IBLL.JudgeandMergeBmpDataperHalfHourV2(file, t, ref bmplist, vehicleid, in para);

                                            if (infostatisticresult != null)
                                            {
                                                _logger.LogError(infostatisticresult);
                                                listresult.Add(infostatisticresult);
                                                canbeimported = false;
                                                break;
                                            }
                                            if (infobrkresult != null)
                                            {
                                                _logger.LogError(infobrkresult);
                                                listresult.Add(infobrkresult);

                                                canbeimported = false;
                                                break;
                                            }
                                            if (infobmpresult != null)
                                            {
                                                _logger.LogError(infobmpresult);
                                                canbeimported = false;
                                                break;
                                            }
                                            if (infogpsresult != null)
                                            {
                                                _logger.LogError(infogpsresult);
                                                listresult.Add(infogpsresult);

                                                canbeimported = false;
                                                break;
                                            }
                                            if (infospdresult != null)
                                            {
                                                _logger.LogError(infospdresult);
                                                listresult.Add(infospdresult);
                                                canbeimported = false;
                                                break;
                                            }
                                            if (infostrresult != null)
                                            {
                                                _logger.LogError(infostrresult);
                                                listresult.Add(infostrresult);
                                                canbeimported = false;
                                                break;
                                            }
                                            if (infothrresult != null)
                                            {
                                                _logger.LogError(infothrresult);
                                                listresult.Add(infothrresult);

                                                canbeimported = false;
                                                break;
                                            }
                                            if (infoengspddisresult != null)
                                            {
                                                _logger.LogError(infoengspddisresult);
                                                listresult.Add(infoengspddisresult);

                                                canbeimported = false;
                                                break;
                                            }
                                            if (infoengspdtimeresult != null)
                                            {
                                                _logger.LogError(infoengspdtimeresult);
                                                listresult.Add(infoengspdtimeresult);

                                                canbeimported = false;
                                                break;
                                            }
                                           
                                        }
                                        Console.WriteLine("读取数据完毕" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        Console.WriteLine("开始存入数据" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        if (canbeimported)
                                        {
                                            listresult.Add("****************" + vehicleid + "日期为" + date + "  半小时数据开始导入****************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                            _logger.LogInformation("****************" + vehicleid + "日期为" + date + "  半小时数据开始导入****************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                            if (gpslist.Count > 0)
                                            {
                                                _IGPSRecord_IBLL.AddAllEntity(gpslist, vehicleid);
                                                //_db.BulkInsert(gpslist);
                                            }
                                            if (brklist.Count > 0)
                                            {
                                                _IBrakeDistribution_IBLL.AddAllEntity(brklist, vehicleid);
                                                //_db.BulkInsert(brklist);
                                            }
                                        
                                            if (strlist.Count > 0)
                                            {
                                                _ISteeringDistribution_IBLL.AddAllEntity(strlist, vehicleid);
                                                //_db.BulkInsert(strlist);
                                            }
                                            if (thrlist.Count > 0)
                                            {
                                                _IThrottleDistribution_IBLL.AddAllEntity(thrlist, vehicleid);
                                                //_db.BulkInsert(thrlist);
                                            }
                                            if (stalist.Count > 0)
                                            {
                                                //不需要合并了，因为现在的原始数据就是半小时合并过的
                                                //var statisticfinallist = StatisticCombined.statisticcombineV2(stalist, vehicleid);
                                                _IAnalysisData_All_Service.AddAllEntity(stalist, vehicleid);
                                                //_db.BulkInsert(stalist);
                                            }
                                            if (spdlist.Count > 0)
                                            {
                                                //var speedfinallist = SpeedCombined.speedcombine(spdlist, vehicleid);
                                                _ISpeedDistribution_ACC_IBLL.AddAllEntity(spdlist, vehicleid);
                                                //_db.BulkInsert(spdlist);
                                            }
                                            if (engspddislist.Count > 0)
                                            {
                                                //var engspddisfinallist = EngineSpeedDistanceCombined.engspddisCombine(engspddislist, vehicleid);
                                                _IEngineSpeedDisDistribution_IBLL.AddAllEntity(engspddislist, vehicleid);
                                                //_db.BulkInsert(spdlist);
                                            }
                                            if (engspdtimelist.Count > 0)
                                            {
                                                //var engspdtimefinallist = EngineSpeedTimeCombined.engspdtimeCombine(engspdtimelist, vehicleid);
                                                _IEngineSpeedTimeDistribution_IBLL.AddAllEntity(engspdtimelist, vehicleid);
                                                //_db.BulkInsert(spdlist);
                                            }
                                            listresult.Add("****************" + vehicleid + "日期为" + date + "  半小时数据导入成功****************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                            _logger.LogInformation("****************" + vehicleid + "日期为" + date + "  半小时数据导入成功****************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        }
                                        Console.WriteLine("存入数据完毕" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                    }
                                    else
                                    {
                                        listresult.Add(vehicleid + "日期为" + date + "半小时路径下无文件");
                                    }
                                }
                                else
                                {
                                    _logger.LogInformation(vehicleid + "日期为" + date + "半小时数据还没有上传完毕");
                                    listresult.Add(vehicleid + "日期为" + date + "半小时数据还没有上传完毕");
                                }

                            }
                            else
                            {
                                _logger.LogInformation(vehicleid + "日期为" + date + "半小时数据已有导入flag");
                                listresult.Add(vehicleid + "日期为" + date + "半小时数据已有导入flag");
                            }


                        }
                        var memoryCacheALL = (MemoryCache)_memoryCache;//先转成MemoryCache，否则无法使用Compact方法
                        memoryCacheALL.Compact(1.0);//清除所有缓存
                                                    //_memoryCache.Compact(1.0);//一旦有新的数据导入到数据库中，就执行一次内存重置，防止还用之前的缓存来展示数据
                    }
                    catch (Exception ex)
                    {
                        listresult.Add($"{filename}文件读取错误：{ex.Message}！");
                        _logger.LogError(ex.Message + "错误发生在" + filename + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                    }
                    return listresult;
                }
                else
                {
                    return new List<string>() { vehicleid + "日期选择为空" };

                }

            }
            else
            {
                return new List<string>() { "未开启允许导入设置" };
            }

        }

        public async Task<List<string>> PumaDataImport(string startdate, string enddate, string vehicleid)
        {
            if (paradict[vehicleid].importaccess == 1)//判断是否允许导入数据
            {

                if (startdate != null && enddate != null)
                {
                    int span = DateTimeOperation.DateDiff(startdate, enddate);
                    inputpath = paradict[vehicleid].importpermileagepath;
                    List<string> listresult = new List<string>();
                    string filename = "";
                    try
                    {
                        var para = paradict[vehicleid];
                        for (int i = 0; i < span + 1; i++)
                        {
                            string date = FileOperator.DatetoName(Convert.ToDateTime(startdate).AddDays(i).ToString("yyyy-MM-dd")).Substring(5);//当前计算的日期文件夹名称
                            string inputfiletimeinfo = Path.Combine(inputpath, date);
                            //string outputfiletimeinfo = Path.Combine(resultpath, date);
                            //判断input子文件夹里是否有导入的flag
                            if (!FileOperator.DataImportCompleteFlag(inputfiletimeinfo))
                            {
                                //判断是否有数据上传完整
                                if (FileOperator.DataTransferCompleteFlag(inputfiletimeinfo, date))
                                {
                                    FileInfo[] filelist = FileOperator.Isfileexist(inputfiletimeinfo);
                                    if (filelist != null && filelist.Length > 0)
                                    {
                                        List<StatisticAll> pumalist = new List<StatisticAll>();
                                        bool canbeimported = true;
                                        Console.WriteLine("开始读取里程模式数据" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        //int fileindex=0;//添加一个文件index序号，存储到数据库中，对后面单位里程的分析数据查询有帮助
                                        foreach (var file in filelist)
                                        {
                                            filename = file.Name;
                                            //读取单个csv文件的数据并存储到t
                                            var t = await CSVFileImport.getAllDatafromCSVforImport(file,false);
                                            var infomileageresult = _IAnalysisData_PUMA_Service.JudgeandMergeMileageData(file, t, ref pumalist, vehicleid, in para);
                                            if (infomileageresult != null)
                                            {
                                                _logger.LogError(infomileageresult);
                                                canbeimported = false;
                                                break;
                                            }
                                        }
                                        Console.WriteLine("读取里程模式数据完毕" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        Console.WriteLine("开始存入里程模式数据" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                        if (canbeimported)
                                        {
                                            _logger.LogInformation("****************" + vehicleid + "日期为" + date + "  里程数据开始导入****************" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                                            listresult.Add( "****************" + vehicleid + "日期为" + date + "  里程数据开始导入****************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                            if (pumalist.Count > 0)
                                            {
                                                _IAnalysisData_PUMA_Service.AddAllEntity(pumalist, vehicleid);
                                                //_db.BulkInsert(strlist);
                                            }
                                            listresult.Add( "****************" + vehicleid + "日期为" + date + "  里程数据导入成功****************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                            _logger.LogInformation("****************" + vehicleid + "日期为" + date + "  里程数据导入成功****************" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                                        }
                                        Console.WriteLine("存入里程模式数据完毕" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                    }
                                    else
                                    {
                                        listresult.Add(vehicleid + "日期为" + date + "路径下无文件" + System.Environment.NewLine);
                                    }
                                }
                                else
                                {
                                    _logger.LogInformation(vehicleid + "日期为" + date + "里程模式数据还没有上传完毕");
                                    listresult.Add(vehicleid + "日期为" + date + "里程模式数据还没有上传完毕" + System.Environment.NewLine);
                                }

                            }
                            else
                            {
                                _logger.LogInformation(vehicleid + "日期为" + date + "里程模式数据已有导入flag");
                                listresult.Add(vehicleid + "日期为" + date + "里程模式数据已有导入flag" + System.Environment.NewLine);
                            }

                           
                        }
                        var memoryCacheALL = (MemoryCache)_memoryCache;//先转成MemoryCache，否则无法使用Compact方法
                        memoryCacheALL.Compact(1.0);//清除所有缓存
                                                    //_memoryCache.Compact(1.0);//一旦有新的数据导入到数据库中，就执行一次内存重置，防止还用之前的缓存来展示数据
                    }
                    catch (Exception ex)
                    {
                        listresult.Add($"{filename}文件读取错误：{ex.Message}！");
                        _logger.LogError(ex.Message + "错误发生在" + filename  + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                    }
                    return listresult;
                }
                else
                {
                    return new List<string>() { vehicleid + "日期选择为空" };

                }

            }
            else
            {
                return new List<string>() { "未开启允许导入设置" };
            }

        }


        //数据库中查询出最新数据的日期返回给前端显示
        public string FinishedDate(string vehicleid)
        {
                var isnull = _ISpeedDistribution_ACC_IBLL.LoadEntities(a => a.VehicleId == vehicleid, vehicleid).OrderBy(a => a.Datadate).Select(a => a.Datadate).LastOrDefault();
                if (isnull != null)
                {
                    var finisheddate = (DateTime)isnull;
                    return finisheddate.AddDays(1).ToShortDateString();
                }
                else
                {
                    return "此车辆目前还没有数据";
                }

        }
        //数据库中查询出最新数据的日期返回给前端显示
        public string FinishedPumaDate(string vehicleid)
        {
            var isnull = _IAnalysisData_PUMA_Service.LoadEntities(a => a.vehicle == vehicleid, vehicleid).OrderBy(a => a.datadate).Select(a => a.datadate).LastOrDefault();
            if (isnull != null)
            {
                
                return isnull?.AddDays(1).ToShortDateString();
            }
            else
            {
                return "此车辆目前还没有数据";
            }

        }
        public string ShowConfiguration(string vehicleid)
        {
            string wft = paradict[vehicleid].WFTImport == 1 ? "true  " : "false  ";
            string gps = paradict[vehicleid].GPSImport ==1 ? "true  " : "false  ";
            string brake = paradict[vehicleid].BrakeImport ==1 ? "true  " : "false  ";
            string throttle = paradict[vehicleid].ThrottleImport == 1 ? "true  " : "false  ";
            string steering = paradict[vehicleid].SteeringImport == 1 ? "true  " : "false  ";
            string speed = paradict[vehicleid].SpeedImport == 1 ? "true  " : "false  ";
            string bump = paradict[vehicleid].BumpImport == 1 ? "true  " : "false  ";
            string statistic = paradict[vehicleid].StatisticImport == 1 ? "true" : "false";
            string engspd = paradict[vehicleid].importengspd == 1 ? "true" : "false";
            string puma = paradict[vehicleid].importpuma == 1 ? "true" : "false";
            var  importresult= "测量轮:" + wft + System.Environment.NewLine+
                "经纬度:"+ gps + System.Environment.NewLine 
                +"刹车:"+ brake + System.Environment.NewLine
                +"油门:"+ throttle + System.Environment.NewLine
                + "转向:" + steering + System.Environment.NewLine
                + "速度:" + speed + System.Environment.NewLine
                + "冲击:" +bump + System.Environment.NewLine
                + "统计值:" + statistic + System.Environment.NewLine
                + "单位里程:" + puma + System.Environment.NewLine
                + "转速:" + engspd;
            return importresult;
        }
        


    }
}
